package exchange

import (
	"global/model"
	"global/core"
	"strings"
	"global/libs/structs"
	"sync"
	"srv/analysis/lib/coin"
	"github.com/shopspring/decimal"
)

const (
	ExchangeOptAdd	 	= iota
	ExchangeOptUpdate
	ExchangeOptDel
)

type sortExchangeAmountData struct {
	Exchange 		string
	Amount 			decimal.Decimal
}

type ExchangeHandle struct{

	ctx  				*core.Context
	exchanges 			map[string]*model.Exchange
	markets 			map[string]map[string]interface{}
	symbols 			map[string]map[string]structs.Symbol

	exchangeHandles 	map[string]*AnalysisExchange

	coinHandle 			*coin.CoinHandler

	SortHandle 			*ExchangeSort

	mux 				sync.Mutex
}

func NewExchangeHandle() *ExchangeHandle {
	return &ExchangeHandle{
		exchanges: 			make(map[string]*model.Exchange),
		markets: 			make(map[string]map[string]interface{}),
		symbols: 			make(map[string]map[string]structs.Symbol),
		exchangeHandles: 	make(map[string]*AnalysisExchange),
	}
}

func (eh *ExchangeHandle) Init(
	coinHandle *coin.CoinHandler,
	ctx *core.Context,
	markets map[string]map[string]interface{},
	exchanges map[string]*model.Exchange,
	symbols map[string]map[string]structs.Symbol) {

	eh.coinHandle = coinHandle
	eh.ctx = ctx
	eh.markets = markets
	eh.exchanges = exchanges
	eh.symbols = symbols
	eh.SortHandle = NewExchangeSort(ctx.GetBaseRedis())
	eh.SortHandle.Run()
}

func (eh *ExchangeHandle) Run() {
	for _, v := range eh.exchanges {
		go func(exchange *model.Exchange) {
			eh.newAnalysisExchange(exchange)
		}(v)
	}
}

func (eh *ExchangeHandle) newAnalysisExchange(exchange *model.Exchange) {
	eh.mux.Lock()
	defer eh.mux.Unlock()

	slug := strings.ToLower(exchange.Slug)
	analysis := NewAnalysisExchange(
		eh.ctx.GetBaseRedis(),
		eh.coinHandle,
		eh.SortHandle,
		exchange, eh.markets[slug],
		eh.symbols[slug])

	go analysis.Start()

	eh.exchangeHandles[slug] = analysis
}

func (eh *ExchangeHandle) UpdateExchange(opt int, exchange *model.Exchange) {
	slug := strings.ToLower(exchange.Slug)
	eh.mux.Lock()
	defer eh.mux.Unlock()

	if _, ok := eh.exchangeHandles[slug]; ok && opt == ExchangeOptAdd {
		return
	} else if !ok && (opt == ExchangeOptUpdate || opt == ExchangeOptDel) {
		return
	}

	switch opt {
	case ExchangeOptAdd:
		eh.newAnalysisExchange(exchange)
	case ExchangeOptUpdate:
		eh.exchangeHandles[slug].ForceUpdateSignal <- exchange
	case ExchangeOptDel:
		eh.exchangeHandles[slug].ExitSignal <- true
	}
}